use crate::reader::binary::core::{Stream, StreamError};

pub struct MemoryStream {
    buffer: Vec<u8>,
    position: usize,
}

impl MemoryStream {
    pub fn new() -> Result<MemoryStream, StreamError> {
        Ok(MemoryStream {
            buffer: Vec::new(),
            position: 0,
        })
    }
}

impl Stream for MemoryStream {
    fn write(&mut self, bytes: &[u8]) -> Result<usize, StreamError> {
        let bytes_out_of_buffer = bytes.len() - (self.buffer.len() - self.position);

        for _ in 0..bytes_out_of_buffer {
            self.buffer.push(0);
        }

        self.buffer[self.position..(self.position + bytes.len())]
            .clone_from_slice(&bytes[..bytes.len()]);

        self.position += bytes.len();

        Ok(bytes.len())
    }

    fn read(&mut self, buffer: &mut [u8]) -> Result<usize, StreamError> {
        if self.position + buffer.len() > self.buffer.len() {
            return Err(StreamError::ReadError);
        }

        let slice = &self.buffer[self.position..(self.position + buffer.len())];
        buffer.clone_from_slice(slice);

        Ok(buffer.len())
    }

    fn seek(&mut self, to: usize) -> Result<usize, StreamError> {
        self.position = to;
        Ok(self.position)
    }

    fn tell(&mut self) -> Result<usize, StreamError> {
        Ok(self.position)
    }
}
